package net.dao;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang.ArrayUtils;

public class DataAccessObjectHelper<DataObject, DataQueryBean extends BaseQueryBean> {

	private IDataAccessInterface<DataObject, DataQueryBean> dao;

	public DataAccessObjectHelper(
			IDataAccessInterface<DataObject, DataQueryBean> dataAccessInterface) {
		super();
		this.dao = dataAccessInterface;
	}

	public void synchronize(DataObject[] datas, DataQueryBean queryBean)
			throws Exception {
		synchronize(datas, queryBean, null);
	}

	public void synchronize(
			final DataObject[] datas,
			final DataQueryBean queryBean,
			net.dao.IDataAccessInterface.ISynchronizeCallback<DataObject> callBack)
			throws Exception {
		List<DataObject> inputList = new ArrayList<DataObject>();

		if (ArrayUtils.isEmpty(datas) == false) {
			inputList.addAll(Arrays.asList(datas));
		} // end if

		DataObject[] existentSysMessageResources = dao.query(queryBean);

		List<DataObject> existentList = new ArrayList<DataObject>();

		if (ArrayUtils.isEmpty(existentSysMessageResources) == false) {
			existentList.addAll(Arrays.asList(existentSysMessageResources));
		} // end if

		List<DataObject> willAddSysMessageResources = ListUtils.subtract(
				inputList, existentList);

		List<DataObject> willDeleteSysMessageResources = ListUtils.subtract(
				existentList, inputList);

		List<DataObject> willUpdateSysMessageResources = ListUtils
				.intersection(existentList, inputList);

		DataObject[] willUpdateSysMessageResourceArray = null;

		if (willUpdateSysMessageResources.isEmpty() == false) {
			willUpdateSysMessageResourceArray = (DataObject[]) Array
					.newInstance(willUpdateSysMessageResources.get(0)
							.getClass(), willUpdateSysMessageResources.size());

			willUpdateSysMessageResourceArray = willUpdateSysMessageResources
					.toArray(willUpdateSysMessageResourceArray);
		}
		
		DataObject[] willAddSysMessageResourceArray = null;

		if (willAddSysMessageResources.isEmpty() == false) {
			willAddSysMessageResourceArray = (DataObject[]) Array
					.newInstance(willAddSysMessageResources.get(0)
							.getClass(), willAddSysMessageResources.size());

			willAddSysMessageResourceArray = willAddSysMessageResources
					.toArray(willAddSysMessageResourceArray);
		}
		
		DataObject[] willDeleteSysMessageResourceArray = null;

		if (willDeleteSysMessageResources.isEmpty() == false) {
			willDeleteSysMessageResourceArray = (DataObject[]) Array
					.newInstance(willDeleteSysMessageResources.get(0)
							.getClass(), willDeleteSysMessageResources.size());

			willDeleteSysMessageResourceArray = willDeleteSysMessageResources
					.toArray(willDeleteSysMessageResourceArray);
		}

		if (callBack != null) {
			callBack.checkSynchronizeObjects(willAddSysMessageResourceArray,
					willUpdateSysMessageResourceArray,
					willDeleteSysMessageResourceArray);
		} // end if

		if (willUpdateSysMessageResources.isEmpty() == false) {
			if (callBack != null) {
				callBack.beforeUpdate(willUpdateSysMessageResourceArray);
			} // end if

			dao.batchUpdate(willUpdateSysMessageResourceArray);

			if (callBack != null) {
				callBack.afterUpdate(willUpdateSysMessageResourceArray);
			} // end if
		} // end if

		if (willAddSysMessageResources.isEmpty() == false) {
			if (callBack != null) {
				callBack.beforeInsert(willAddSysMessageResourceArray);
			} // end if

			dao.batchInsert(willAddSysMessageResourceArray);

			if (callBack != null) {
				callBack.afterInsert(willAddSysMessageResourceArray);
			} // end if
		} // end if

		if (willDeleteSysMessageResources.isEmpty() == false) {
			if (callBack != null) {
				callBack.beforeDelete(willDeleteSysMessageResourceArray);
			} // end if

			for (int i = 0; i < willDeleteSysMessageResourceArray.length; i++) {
				DataObject object = willDeleteSysMessageResourceArray[i];
				dao.delete(object);
			} // end for

			if (callBack != null) {
				callBack.afterDelete(willDeleteSysMessageResourceArray);
			} // end if
		} // end if

	}

}
